package cn.sciento.farm.devicemanager.gateway.uplink.service.deepsoil;

import cn.sciento.farm.devicemanager.common.constant.CollectionTypeEnum;
import cn.sciento.farm.devicemanager.common.constant.DeviceConstant;
import cn.sciento.farm.devicemanager.common.constant.MqttConstant;
import cn.sciento.farm.devicemanager.common.constant.RedisConstant;
import cn.sciento.farm.devicemanager.common.util.NumberUtil;
import cn.sciento.farm.devicemanager.common.util.RedisUtil;
import cn.sciento.farm.devicemanager.dao.entity.DevCollection;
import cn.sciento.farm.devicemanager.dao.entity.DevCollectionHistory;
import cn.sciento.farm.devicemanager.dao.entity.DevDevice;
import cn.sciento.farm.devicemanager.gateway.model.uplink.CollectionData;
import cn.sciento.farm.devicemanager.gateway.uplink.service.base.AbstractStringAdapter;
import cn.sciento.farm.devicemanager.gateway.uplink.service.sensor.AlarmDisposeService;
import cn.sciento.farm.devicemanager.gateway.uplink.service.sensor.MessageAllDisposeService;
import cn.sciento.farm.devicemanager.service.CollectionHistoryService;
import cn.sciento.farm.devicemanager.service.CollectionService;
import cn.sciento.farm.devicemanager.service.CollectionTypeService;
import cn.sciento.farm.devicemanager.service.DeviceService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author walton
 * @description
 * @date 2020/12/24 10:24
 */
@Slf4j
@Service(value = MqttConstant.PROTOCOL_PREFIX + MqttConstant.PROTOCOL_SOIL)
public class DeepSoilDataAdapter extends AbstractStringAdapter {

    @Autowired
    private MessageAllDisposeService messageAllDisposeService;

    @Autowired
    private CollectionHistoryService collectionHistoryService;

    @Autowired
    CollectionTypeService collectionTypeService;

    @Autowired
    private CollectionService collectionService;

    @Autowired
    private AlarmDisposeService alarmService;

    @Autowired
    DeviceService deviceService;

    @Override
    public void analyseStringData(String[] subTopic, String message) {
        if (subTopic.length == 3) {
            log.info("适配器  topic  {}  msg   {}", Arrays.toString(subTopic), message);
            switch (subTopic[1]) {
                case MqttConstant.UP:
                    List<CollectionData> collectionDataList = messageDispose(subTopic[2], message);
                    for (CollectionData collectionData : collectionDataList) {
                        DevCollection deviceCollection = collectionService.getByDeepSoilArg(
                                collectionData.getEui(),
                                collectionData.getNode(),
                                collectionData.getName());
                        if (deviceCollection == null) {
                            deviceCollection = createCollection(collectionData);
                        }
                        if (deviceCollection == null){
                            return;
                        }
                        long currentTimeMillis = System.currentTimeMillis();
                        collectionService.updateData(deviceCollection.getId(), collectionData.getData(), currentTimeMillis);
                        DevCollectionHistory history = new DevCollectionHistory();
                        history.setCollectionId(deviceCollection.getId());
                        history.setLastData(collectionData.getData());
                        history.setLastTime(currentTimeMillis);
                        history.setTenantId(deviceCollection.getTenantId());
                        deviceCollection.setLastTime(currentTimeMillis);
                        collectionHistoryService.insert(history);
                        alarmService.dispatch(deviceCollection);
                    }
                    break;
                case MqttConstant.OFFLINE:
                    Map map = JSON.parseObject(message).getInnerMap();
                    if (map == null) {
                        return;
                    }
                    String node = "" + map.get("id");
                    if (!StringUtils.isEmpty(node)) {
                        messageAllDisposeService.changeCollectionStatus(subTopic[2], node, 0);
                        break;
                    }
                    break;
                default:
                    break;
            }
        }
    }
    private List<CollectionData> messageDispose(String eui, String message){
        Map<String, Object> map = JSON.parseObject(message).getInnerMap();
        String node = "" + map.get("id");
        map.remove("id");
        List<CollectionData> deviceDataList = new ArrayList<>();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String key = entry.getKey();
            if ("status".equals(key)) {
                key = "";
            }
            String value = ""+ entry.getValue();
            Map<String, Object> valueMap = (Map<String, Object>) JSON.parse(value);
            for (Map.Entry<String, Object> valueEntry : valueMap.entrySet()) {
                String valueEntryKey = valueEntry.getKey();
                int valueEntryValue = ((Number) valueEntry.getValue()).intValue();
                String circuit = transType(valueEntryKey);
                CollectionData collectionData = new CollectionData();
                CollectionTypeEnum devCollectionType = CollectionTypeEnum.get(circuit);
                Integer proportion = devCollectionType.getProportion();
                collectionData.setEui(eui);
                collectionData.setNode(node);
                collectionData.setName(node + "#" + key + devCollectionType.getName());
                collectionData.setType(circuit);
                collectionData.setCircuit(circuit);
                collectionData.setProtocol(DeviceConstant.SIMPLE);
                collectionData.setData(computeRealValue(proportion, valueEntryValue));
                if ("num".equals(valueEntryKey)) {
                    collectionData.setName(node + "#土壤层数");
                    collectionData.setType("");
                    collectionData.setCircuit("");
                    collectionData.setData(computeRealValue(1, valueEntryValue));
                }
                deviceDataList.add(collectionData);
            }
        }
        return deviceDataList;
    }

    private String transType(String circuit) {
        if ("C".equals(circuit)) {
            circuit = "soilC";
            return circuit;
        }
        if ("T".equals(circuit)) {
            circuit = "soilT";
            return circuit;
        }
        if ("H".equals(circuit)) {
            circuit = "soilH";
            return circuit;
        }
        return circuit;
    }

    private DevCollection createCollection(CollectionData collectionData){
        synchronized (this){
            String lock = RedisUtil.getCacheStr(String.format(RedisConstant.CREATE_COLLECTION,
                    collectionData.getEui(),collectionData.getNode(),collectionData.getCircuit()));
            if(lock == null){
                RedisUtil.putCacheStr(String.format(RedisConstant.CREATE_COLLECTION,
                        collectionData.getEui(),collectionData.getNode(),collectionData.getCircuit()),"1",20L);
            }else {
                return null;
            }
        }
        String protocol = collectionData.getProtocol();
        int sequence = 0;
        DevDevice devDevice = deviceService.getById(collectionData.getEui());
        if (devDevice == null) {
            return null;
        }
        if (DeviceConstant.SIMPLE.equals(protocol)) {
            sequence = Integer.parseInt(collectionData.getNode());
        }
        DevCollection collection = new DevCollection();
        collection.setSequence(sequence);
        collection.setName(collectionData.getName());
        collection.setEui(collectionData.getEui());
        collection.setCircuit(collectionData.getCircuit());
        collection.setNode(collectionData.getNode());
        collection.setOnline(1);
        collection.setLastData(collectionData.getData());
        collection.setTenantId(devDevice.getTenantId());
        collection.setProtocol(DeviceConstant.SIMPLE);
        collection.setType(collectionData.getType());
        System.out.println(collection);
        collectionService.insert(collection);
        return collection;

    }

    private float computeRealValue(Integer proportion, Object value) {
        int originValue = ((Number) value).intValue();
        double realValue = originValue * 1.0 / proportion;
        // 执行表达式
        return NumberUtil.double2float(realValue, 2);
    }
}
